home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / gs241j11.zip / ZCOMP.C < prev    next >
C/C++ Source or Header  |  1992-07-01  |  25KB  |  1,140 lines

  1. /*
  2.  * Composite String Decoding Utility
  3.  *
  4.  * Copyright (C) 1991,1992 Norio Katayama.
  5.  * Aug.17, 1991 Programmed by N.Katayama (katayama@nacsis.ac.jp)
  6.  * May. 2, 1992 Revised by N.Katayama
  7.  */
  8.  
  9. #include "memory_.h"
  10. #include "ghost.h"
  11. #include "errors.h"
  12. #include "oper.h"
  13. #include "gxfixed.h"            /* for gxmatrix.h */
  14. #include "gxmatrix.h"
  15. #include "gschar.h"
  16. #include "gxdevice.h"            /* for gxfont.h */
  17. #include "gxfont.h"
  18. #include "gspath.h"
  19. #include "gzstate.h"
  20. #include "alloc.h"
  21. #include "dict.h"
  22. #include "font.h"
  23. #include "iutil.h"
  24. #include "name.h"
  25. #include "estack.h"
  26. #include "state.h"
  27. #include "store.h"
  28.  
  29. #undef DEBUG
  30.  
  31. #define es_comp 999     /* probable to conflict with other definition */
  32. #define FontStackDepth  5
  33.  
  34. /* Imported functions */
  35.  
  36. extern int zshow(P1(os_ptr)), zashow(P1(os_ptr));
  37. extern int zwidthshow(P1(os_ptr)), zawidthshow(P1(os_ptr));
  38. extern int zcharpath(P1(os_ptr)), zstringwidth(P1(os_ptr));
  39. extern int zload(P1(os_ptr));
  40. extern int add_FID(P2(ref *, gs_font *));
  41.  
  42. /* Imported varables */
  43.  
  44. extern gs_font_dir *ifont_dir;
  45. extern ref name_FID;
  46. extern ref name_FontMatrix;
  47.  
  48. /* Font context */
  49.  
  50. struct context {
  51.     /* Font stack */
  52.     ref dictstack[FontStackDepth];
  53.     gs_font *fontstack[FontStackDepth];
  54.         int fdepth;
  55.     /* Mapping information */
  56.     int font_no[FontStackDepth];
  57.     int modal[FontStackDepth];
  58.     /* String */
  59.         byte *buffer;
  60.     int buffer_size;
  61.         byte *str;
  62.         int len;
  63.     byte code;        /* result of font mapping decoder */
  64.     /* Procedures */
  65.     int (*base_proc)(P2(os_ptr, struct context *));
  66.     int (*final_proc)(P2(os_ptr, struct context *));
  67.     /* Procedure tags */
  68.     int in_cshow;        /* true if in cshow */
  69.     int index;        /* index of op_def_table */
  70.     float axy[2];        /* for ashow and awidthshow */
  71.     float cxy[2];        /* for widthshow and awidthshow */
  72.     char_code wschar;        
  73.     float wxy[2];        /* for stringwidth */
  74.     int charpath_flag;    /* for charpath */
  75.     ref cshow_proc;        /* for cshow */
  76. };
  77.  
  78. typedef int (*comp_proc)(P2(os_ptr, struct context *));
  79.  
  80. /* Forward declarations */
  81.  
  82. private int base_show(P2(os_ptr, struct context *));
  83. private int base_ashow(P2(os_ptr, struct context *));
  84. private int base_widthshow(P2(os_ptr, struct context *));
  85. private int base_awidthshow(P2(os_ptr, struct context *));
  86. private int base_charpath(P2(os_ptr, struct context *));
  87. private int base_stringwidth(P2(os_ptr, struct context *));
  88. private int final_stringwidth(P2(os_ptr, struct context *));
  89. private int base_cshow(P2(os_ptr, struct context *));
  90.  
  91. private int setup_context(P4(os_ptr, comp_proc, comp_proc, struct context **));
  92. private int free_context(P1(struct context *));
  93. private int comp_continue(P1(os_ptr));
  94.  
  95. private int FMapType2(P1(struct context *));
  96. private int FMapType3(P1(struct context *));
  97. private int FMapType4(P1(struct context *));
  98. private int FMapType5(P1(struct context *));
  99. private int FMapType6(P1(struct context *));
  100. private int FMapType7(P1(struct context *));
  101. private int FMapType8(P1(struct context *));
  102.  
  103. private int push_font(P3(struct context *, int, int));
  104. private int pop_font(P1(struct context *));
  105. private int getwschar(P1(struct context *));
  106. private int comp_setfont(P1(struct context *));
  107.  
  108. private int i_zshow0;
  109. private int i_zashow0;
  110. private int i_zwidthshow0;
  111. private int i_zawidthshow0;
  112. private int i_zcharpath0;
  113. private int i_zstringwidth0;
  114. private int i_zcshow0;
  115.  
  116. #define check_currentpoint(pgs)    \
  117. { gs_point pt; if((code = gs_currentpoint(pgs, &pt)) < 0) return code; }
  118.  
  119. /*
  120.  * show0
  121.  */
  122.  
  123. int
  124. zshow0(register os_ptr op)
  125. {
  126.     int code;
  127.     struct context *context;
  128.  
  129.     if((code = setup_context(op, base_show, NULL, &context)) < 0)
  130.         return code;
  131.     check_currentpoint(igs);
  132.     pop(1);
  133.     op --;
  134.     context->index = i_zshow0;
  135.         return comp_continue(op);
  136. }
  137.  
  138. /*
  139.  * ashow0
  140.  */
  141.  
  142. int
  143. zashow0(register os_ptr op)
  144. {
  145.     int code;
  146.     struct context *context;
  147.  
  148.     if((code = setup_context(op, base_ashow, NULL, &context)) < 0)
  149.         return code;
  150.     if((code = num_params(op - 1, 2, context->axy)) < 0)
  151.         return code;
  152.     check_currentpoint(igs);
  153.     pop(3);
  154.     op -= 3;
  155.     context->index = i_zashow0;
  156.     return comp_continue(op);
  157. }
  158.     
  159. /*
  160.  * widthshow()
  161.  */
  162.  
  163. int
  164. zwidthshow0(register os_ptr op)
  165. {
  166.     int code;
  167.     struct context *context;
  168.  
  169.     if((code = setup_context(op, base_widthshow, NULL, &context)) < 0)
  170.         return code;
  171.     check_type(op[-1], t_integer);
  172.     context->wschar = (char_code)op[-1].value.intval;
  173.     if((code = num_params(op - 2, 2, context->cxy)) < 0)
  174.         return code;
  175.     check_currentpoint(igs);
  176.     pop(4);
  177.     op -= 4;
  178.     context->index = i_zwidthshow0;
  179.     return comp_continue(op);
  180. }
  181.  
  182. /*
  183.  * awidthshow()
  184.  */
  185.  
  186. int
  187. zawidthshow0(register os_ptr op)
  188. {
  189.     int code;
  190.     struct context *context;
  191.  
  192.     if((code = setup_context(op, base_awidthshow, NULL, &context)) < 0)
  193.         return code;
  194.     if((code = num_params(op - 1, 2, context->axy)) < 0)
  195.         return code;
  196.     check_type(op[-3], t_integer);
  197.     context->wschar = (char_code)op[-3].value.intval;
  198.     if((code = num_params(op - 4, 2, context->cxy)) < 0)
  199.         return code;
  200.     check_currentpoint(igs);
  201.     pop(6);
  202.     op -= 6;
  203.     context->index = i_zawidthshow0;
  204.     return comp_continue(op);
  205. }
  206.  
  207. /*
  208.  * charpath0()
  209.  */
  210.  
  211. int
  212. zcharpath0(register os_ptr op)
  213. {
  214.     int code;
  215.     struct context *context;
  216.  
  217.     if((code = setup_context(op - 1, base_charpath, NULL, &context)) < 0)
  218.         return code;
  219.     check_type(*op, t_boolean);
  220.     context->charpath_flag = op->value.index;
  221.     check_currentpoint(igs);
  222.     pop(2);
  223.     op -= 2;
  224.     context->index = i_zcharpath0;
  225.     return comp_continue(op);
  226. }
  227.  
  228. /*
  229.  * stringwidth0
  230.  */
  231.  
  232. int
  233. zstringwidth0(register os_ptr op)
  234. {
  235.     int code;
  236.     struct context *context;
  237.     
  238.     if((code = setup_context(op, base_stringwidth, 
  239.                  final_stringwidth, &context)) < 0)
  240.         return code;
  241.     context->wxy[0] = 0;
  242.     context->wxy[1] = 0;
  243.     push(1);
  244.     make_int(op - 1, 0);    /* Dummy x */
  245.     make_int(op, 0);    /* Dummy y */
  246.     context->index = i_zstringwidth0;
  247.     return comp_continue(op);
  248. }
  249.  
  250. /*
  251.  * cshow
  252.  */
  253.  
  254. int
  255. zcshow0(register os_ptr op)
  256. {
  257.     int code;
  258.     struct context *context;
  259.  
  260.     if((code = setup_context(op, base_cshow, NULL, &context)) < 0)
  261.         return code;
  262.     check_proc(op[-1]);
  263.     context->in_cshow = 1;
  264.     context->cshow_proc = op[-1];
  265.     pop(2);
  266.     op -= 2;
  267.     context->index = i_zcshow0;
  268.     return comp_continue(op);
  269. }
  270.  
  271. /*
  272.  * rootfont
  273.  */
  274.  
  275. int
  276. zrootfont(register os_ptr op)
  277. {
  278.     push(1);
  279.     *op = istate.rootfont;
  280.     return 0;
  281. }
  282.  
  283. /*
  284.  * findencoding
  285.  * Note: there is no encoding dictionary defined in files.
  286.  */
  287.  
  288. int
  289. zfindencoding(register os_ptr op)
  290. {
  291.     return zload(op);
  292. }
  293.  
  294. /* -------- Initialization procedure -------- */
  295.  
  296. ref name_FDepVector;
  297.  
  298. #ifdef DEBUG
  299. ref name_FontName;
  300. #endif
  301.  
  302. private void
  303. zcomp_init()
  304. {    
  305.     static names_def fnd[] = {
  306.         { "FDepVector", &name_FDepVector },
  307. #ifdef DEBUG
  308.         { "FontName", &name_FontName },
  309. #endif
  310.         /* Mark the end of the initalized name list. */
  311.         names_def_end
  312.     };
  313.  
  314.     init_names(fnd);
  315. }
  316.  
  317. op_def zcomp_op_defs[] = {
  318.         {"1show0", zshow0, &i_zshow0},
  319.     {"3ashow0", zashow0, &i_zashow0},
  320.     {"4widthshow0", zwidthshow0, &i_zwidthshow0},
  321.     {"6awidthshow0", zawidthshow0, &i_zawidthshow0},
  322.     {"2charpath0", zcharpath0, &i_zcharpath0},
  323.     {"1stringwidth0", zstringwidth0, &i_zstringwidth0},
  324.     {"2cshow0", zcshow0, &i_zcshow0},
  325.     {"1rootfont", zrootfont},
  326.     {"1findencoding", zfindencoding},
  327.  
  328.     op_def_end(zcomp_init)
  329. };
  330.         
  331. /* -------- Internal procedures -------- */
  332.  
  333. private int
  334. base_show(os_ptr op, struct context *context)
  335. {
  336. #ifdef DEBUG
  337.         fprintf(stderr, "base_show: %02X\n", context->code);
  338. #endif
  339.     push(1);
  340.         make_tasv(op, t_string, a_all, 1, bytes, &context->code);
  341.  
  342.     check_estack(1);
  343. #ifdef DEBUG
  344.     fprintf(stderr, "context->index:%d\n", context->index);
  345. #endif
  346.     push_op_estack(zshow, context->index);
  347.     return o_push_estack;
  348. }
  349.  
  350. private int
  351. base_ashow(os_ptr op, struct context *context)
  352. {
  353.     push(3);
  354.     make_real(op - 2, context->axy[0]);
  355.     make_real(op - 1, context->axy[1]);
  356.     make_tasv(op, t_string, a_all, 1, bytes, &context->code);
  357.  
  358.     check_estack(1);
  359.     push_op_estack(zashow, context->index);
  360.     return o_push_estack;
  361. }
  362.  
  363. private int
  364. base_widthshow(os_ptr op, struct context *context)
  365. {
  366.     int wschar;
  367.     
  368.     if((wschar = getwschar(context)) < 0) {
  369.         push(1);
  370.         make_tasv(op, t_string, a_all, 1, bytes, &context->code);
  371.         
  372.         check_estack(1);
  373.         push_op_estack(zshow, context->index);
  374.         return o_push_estack;
  375.     }
  376.     else {
  377.         push(4);
  378.         make_real(op - 3, context->cxy[0]);
  379.         make_real(op - 2, context->cxy[1]);
  380.         make_int(op - 1, wschar);
  381.         make_tasv(op, t_string, a_all, 1, bytes, &context->code);
  382. #ifdef DEBUG
  383.         fprintf(stderr, "wschar: %02X, code: %02X\n",
  384.             wschar, context->code);
  385. #endif
  386.         check_estack(1);
  387.         push_op_estack(zwidthshow, context->index);
  388.         return o_push_estack;
  389.     }
  390. }
  391.  
  392. private int
  393. base_awidthshow(os_ptr op, struct context *context)
  394. {
  395.     int wschar;
  396.     
  397.     if((wschar = getwschar(context)) < 0) {
  398.         push(3);
  399.         make_real(op - 2, context->axy[0]);
  400.         make_real(op - 1, context->axy[1]);
  401.         make_tasv(op, t_string, a_all, 1, bytes, &context->code);
  402.         
  403.         check_estack(1);
  404.         push_op_estack(zashow, context->index);
  405.         return o_push_estack;
  406.     }
  407.     else {
  408.         push(6);
  409.         make_real(op - 5, context->cxy[0]);
  410.         make_real(op - 4, context->cxy[1]);
  411.         make_int(op - 3, wschar);
  412.         make_real(op - 2, context->axy[0]);
  413.         make_real(op - 1, context->axy[1]);
  414.         make_tasv(op, t_string, a_all, 1, bytes, &context->code);
  415.         
  416.         check_estack(1);
  417.         push_op_estack(zawidthshow, context->index);
  418.         return o_push_estack;
  419.     }
  420. }
  421.  
  422. private int
  423. base_charpath(os_ptr op, struct context *context)
  424. {
  425.     push(2);
  426.     make_tasv(op - 1, t_string, a_all, 1, bytes, &context->code);
  427.     make_bool(op, context->charpath_flag);
  428.  
  429.     check_estack(1);
  430.     push_op_estack(zcharpath, context->index);
  431.     return o_push_estack;
  432. }
  433.  
  434. private int
  435. base_stringwidth(os_ptr op, struct context *context)
  436. {
  437.     int code;
  438.     float wxy[2];
  439.  
  440.     if((code = num_params(op, 2, wxy)) < 0)
  441.         return code;
  442. #ifdef DEBUG
  443.     fprintf(stderr, "wxy : %g, %g\n", wxy[0], wxy[1]);
  444.     fprintf(stderr, "context->wxy : %g, %g\n", 
  445.         context->wxy[0], context->wxy[1]);
  446. #endif
  447.     context->wxy[0] += wxy[0];
  448.     context->wxy[1] += wxy[1];
  449.     pop(1);
  450.     op --;
  451.     make_tasv(op, t_string, a_all, 1, bytes, &context->code);
  452.  
  453.     check_estack(1);
  454.     push_op_estack(zstringwidth, context->index);
  455.     return o_push_estack;
  456. }
  457.  
  458. private int
  459. final_stringwidth(os_ptr op, struct context *context)
  460. {
  461.     int code;
  462.     float wxy[2];
  463.  
  464.     if((code = num_params(op, 2, wxy)) < 0)
  465.         return code;
  466.     context->wxy[0] += wxy[0];
  467.     context->wxy[1] += wxy[1];
  468. #ifdef DEBUG
  469.     fprintf(stderr, "final_stringwidth: %g, %g\n",
  470.         context->wxy[0], context->wxy[1]);
  471. #endif
  472.     make_real(op - 1, context->wxy[0]);
  473.     make_real(op, context->wxy[1]);
  474.     return 0;
  475. }
  476.     
  477. private int
  478. base_cshow(os_ptr op, struct context *context)
  479. {
  480.     push(2);
  481.     make_int(op - 1, context->code);
  482.     make_tasv(op, t_string, a_all, 1, bytes, &context->code);
  483. #ifdef DEBUG
  484.     fprintf(stderr, "base_cshow: %02X\n", context->code);
  485. #endif
  486.     check_estack(2);
  487.     esp ++;
  488.     ref_assign(esp, &context->cshow_proc);
  489.     push_op_estack(zstringwidth, context->index);
  490.     return o_push_estack;
  491. }
  492.  
  493. /* -------- Internal routines -------- */
  494.  
  495. #ifdef DEBUG
  496. private int
  497. fprints(FILE *fp, byte *str, int len)
  498. {
  499.     int i;
  500.  
  501.     for(i=0; i<len; i++)
  502.         fprintf(fp, "%02X ", str[i]);
  503.     fprintf(fp, "\n");
  504. }
  505. #endif
  506.  
  507. /*
  508.  * Setup the context structure
  509.  */
  510.  
  511. private int
  512. setup_context(os_ptr pref, int (*base_proc)(), int (*final_proc)(),
  513.           struct context **result)
  514. {
  515.     byte *str;
  516.     int len;
  517.     struct context *context;
  518.  
  519.     check_type(*pref, t_string);
  520.     str = pref->value.bytes;
  521.     len = r_size(pref);
  522. #ifdef DEBUG
  523.     fprintf(stderr, "setup_context(): ");
  524.     fprints(stderr, str, len);
  525. #endif
  526.     /* Allocate context structure */
  527.     context = (struct context *)
  528.         gs_malloc(1, sizeof(struct context), "comp_decode");
  529.     if(context == 0)
  530.         return e_VMerror;
  531.  
  532.     /* Font stack */
  533.         context->fdepth = 0;
  534.     context->dictstack[0] = istate.font;
  535.     context->fontstack[0] = igs->font;
  536. #ifdef DEBUG
  537.     fprintf(stderr, "fontstack[0]: %08X\n", context->fontstack[0]);
  538. #endif
  539.     /* Mapping information */
  540.     context->font_no[0] = -1;    /* specify undefined */
  541.     context->modal[0] = -1;        /* specify undefined */
  542.  
  543.     /* String */
  544.     context->buffer_size = len + 1;
  545.     context->buffer = (byte *)
  546.         gs_malloc(context->buffer_size, 1, "comp_decode");
  547.     if(context->buffer == 0)
  548.         return e_VMerror;
  549.     memcpy(context->buffer, str, len);
  550.     context->str = context->buffer;
  551.     context->len = len;
  552.  
  553.     /* procedures */
  554.     context->base_proc = base_proc;
  555.     context->final_proc = final_proc;
  556.  
  557.     /* procedure tags */
  558.     context->in_cshow = 0;
  559.  
  560.     /* Push the context structure in the e-stack */
  561.     check_estack(2);
  562.     mark_estack(es_comp);
  563.     esp ++;
  564.     make_tasv(esp, t_string, 0, sizeof(struct context), 
  565.           bytes, (byte *)context);
  566.  
  567.     if(result != NULL)
  568.         *result = context;
  569.     return 0;
  570. }
  571.  
  572. /*
  573.  * Free context structure
  574.  */
  575.  
  576. private int
  577. free_context(struct context *context)
  578.  
  579. {
  580.     gs_free((char *)context->buffer, context->buffer_size,1,"comp_decode");
  581.     gs_free((char *)context, 1, sizeof(struct context), "comp_decode");
  582.     return 0;
  583. }
  584.  
  585. /*
  586.  * Composite String Procedure
  587.  */
  588.  
  589. private int
  590. comp_continue(register os_ptr op)
  591. {
  592.         int code;
  593.     struct context *context = (struct context *)esp->value.bytes;
  594.     ref *dictstack = context->dictstack;
  595.     gs_font **fontstack = context->fontstack;
  596. #ifdef DEBUG
  597.     fprintf(stderr, "comp_continue()\n");
  598.     fprintf(stderr, "context->str : ");
  599.     fprints(stderr, context->str, context->len);
  600.     { gs_point pt; gs_currentpoint(igs, &pt);
  601.       fprintf(stderr, "currentpoint: %g, %g\n", pt.x, pt.y);
  602.         }
  603. #endif
  604.     /* pop non-modal fonts */
  605.     pop_font(context);
  606.  
  607.     /* restore currentfont */
  608.     if((code= gs_setfont(igs, fontstack[0])) < 0)
  609.         return code;
  610.     istate.font = dictstack[0];
  611.  
  612.     if(context->len == 0) {
  613.         /* Execute Final Procedure */
  614.         if(context->final_proc != NULL &&
  615.            (code = context->final_proc(op, context)) < 0)
  616.                 return code;
  617.         esp -= 2;
  618.         free_context(context);
  619.         return o_pop_estack;
  620.     }
  621.  
  622.     for(;;) {
  623.         gs_font *pfont = fontstack[context->fdepth];
  624.         gs_type0_data *pdata = &pfont->data.type0_data;
  625. #ifdef DEBUG
  626.         fprintf(stderr, "Font Mapping Loop %d\n", context->fdepth);
  627.         {
  628.             char buffer[256];
  629.             ref *pfname;
  630.             if(dict_find(&dictstack[context->fdepth], 
  631.                      &name_FontName, &pfname) <= 0 ||
  632.                !r_has_type(pfname, t_name))
  633.                 fprintf(stderr, "Failed to get FontName\n");
  634.             else {
  635.                 strncpy(buffer, 
  636.                     pfname->value.pname->string_bytes,
  637.                     pfname->value.pname->string_size);
  638.                 buffer[pfname->value.pname->string_size] = 0;
  639.                 fprintf(stderr, "%s\n", buffer);
  640.             }
  641.         }
  642. #endif
  643.         if(pfont->FontType != ft_composite)
  644.             break;
  645.  
  646.                 if(context->fdepth >= FontStackDepth - 1)
  647.                         return e_rangecheck;
  648.  
  649. #ifdef DEBUG
  650.         fprintf(stderr, "FMapType: %d\n", pdata->FMapType);
  651. #endif
  652.                 switch(pdata->FMapType) {
  653.                 case 2:
  654.             code = FMapType2(context);
  655.             break;
  656.                 case 3:
  657.             code = FMapType3(context);
  658.             break;
  659.                 case 4:
  660.                         code = FMapType4(context);
  661.                         break;
  662.                 case 5:
  663.                         code = FMapType5(context);
  664.                         break;
  665.                 case 6:
  666.                         code = FMapType6(context);
  667.             break;
  668.         case 7:
  669.                         code = FMapType7(context);
  670.                         break;
  671.                 case 8:
  672.                         code = FMapType8(context);
  673.                         break;
  674.         default:
  675.             return e_invalidfont;
  676.                 }
  677.         if(code < 0)
  678.             return code;
  679.         }
  680.  
  681.     context->code = *context->str;
  682.     context->str ++;
  683.     context->len --;
  684.  
  685.     comp_setfont(context);
  686.  
  687.     check_estack(1);
  688.     push_op_estack(comp_continue, context->index);
  689.  
  690.     /* Execute Base Procedure */
  691.     if((code = context->base_proc(op, context)) < 0)
  692.             return code;
  693.  
  694.     return o_push_estack;
  695. }
  696.  
  697. /* -------- Font Map Decoders -------- */
  698.  
  699. /*
  700.  * 8/8 Mapping Decoder
  701.  */
  702.  
  703. private int
  704. FMapType2(struct context *context)
  705. {
  706.         int code, font_no;
  707.  
  708.         if(context->len < 2)
  709.         return e_rangecheck;
  710.  
  711.     font_no = context->str[0];
  712.  
  713.     if((code = push_font(context, font_no, 0)) < 0)
  714.         return code;
  715.     
  716.     context->str ++;
  717.     context->len --;
  718.     return 0;
  719. }
  720.         
  721. /*
  722.  * Escape Mapping Decoder
  723.  */
  724.  
  725. private int
  726. FMapType3(struct context *context)
  727. {
  728.         byte esc_char;
  729.     int code, font_no;
  730.     gs_font *proot = igs->rootfont;
  731.     gs_font *pfont = context->fontstack[context->fdepth];
  732.     
  733.     if(context->len <= 0)
  734.         return e_rangecheck;
  735.  
  736.     /* Determine Escape Character */
  737.  
  738.     if(proot->data.type0_data.FMapType == 3 ||
  739.        proot->data.type0_data.FMapType == 7)
  740.         esc_char = proot->data.type0_data.EscChar;
  741.     else
  742.         esc_char = pfont->data.type0_data.EscChar;
  743. #ifdef DEBUG
  744.     fprintf(stderr, "EscChar: %02X\n", esc_char);
  745. #endif
  746.     if(context->str[0] == esc_char) {
  747.         if(context->str[1] == esc_char) {
  748.             /* Upward font tree */
  749.             pop_font(context);
  750.             context->str ++;
  751.             context->len --;
  752.             return 0;
  753.         }
  754.         if(context->len < 3)
  755.             return e_rangecheck;
  756.         font_no = context->str[1];
  757.         context->str += 2;
  758.         context->len -= 2;
  759.  
  760.         if((code = push_font(context, font_no, 1)) < 0)
  761.             return code;
  762.  
  763.         /* 
  764.          * If the pushed font (i.e. currentfont) is a base font
  765.          * and the next character is the escape character again,
  766.          * then restore the parent composite font to currentfont.
  767.          */
  768.  
  769.         if((context->fontstack[context->fdepth]->FontType != 
  770.             ft_composite) && (context->str[0] == esc_char))
  771.             pop_font(context);
  772.     }
  773.     else {
  774.         if(context->font_no[context->fdepth] < 0)
  775.             context->font_no[context->fdepth] = 0;
  776.         font_no = context->font_no[context->fdepth];
  777.  
  778.         if((code = push_font(context, font_no, 1)) < 0)
  779.             return code;
  780.     }
  781.  
  782.     return 0;
  783. }
  784.  
  785. /*
  786.  * 1/7 Mapping Decoder
  787.  */
  788.  
  789. private int
  790. FMapType4(struct context *context)
  791. {
  792.     int code, font_no;
  793.  
  794.     if(context->len < 1)
  795.         return e_rangecheck;
  796.  
  797.     font_no = (context->str[0] & 0x80 ? 1 : 0);
  798.  
  799.     if((code = push_font(context, font_no, 0)) < 0)
  800.         return code;
  801.  
  802.     *context->str &= 0x7f;
  803.     return 0;
  804. }
  805.  
  806. /*
  807.  * 9/7 Mapping Decoder
  808.  */
  809.  
  810. private int
  811. FMapType5(struct context *context)
  812. {
  813.         int code, font_no;
  814.  
  815.     if(context->len < 2)
  816.         return e_rangecheck;
  817.     
  818.     font_no = context->str[0] * 2 + (context->str[1] & 0x80 ? 1 : 0);
  819.  
  820.     if((code = push_font(context, font_no, 0)) < 0)
  821.         return code;
  822.  
  823.     context->str[1] &= 0x7f;
  824.     context->str ++;
  825.     context->len --;
  826.     return 0;
  827. }
  828.  
  829. /*
  830.  * SubsVector Mapping Decoder
  831.  */
  832.  
  833. private int
  834. FMapType6(struct context *context)
  835. {
  836.     ulong value, range;
  837.     int i, code, font_no, width;
  838.     gs_font *pfont = context->fontstack[context->fdepth];
  839.     gs_type0_data *pdata = &pfont->data.type0_data;
  840.  
  841.     if((width = pdata->subs_width) > 4) 
  842.         return e_invalidfont;    /* width cannot be greater than 4 */
  843.     if(context->len < width)
  844.         return e_rangecheck;
  845.  
  846.     /* Get the value from the string */
  847.     for(i=0, value=0; i<width; i++)
  848.         value = value * 256 + context->str[i];
  849.     /* Get the font number and the character code */
  850.     for(font_no=0; font_no<pdata->subs_size; font_no++) {
  851.         byte *psubs = pdata->SubsVector + font_no*width;
  852.         for(i=0, range=0; i<width; i++)
  853.             range = range * 256 + psubs[i];
  854.         if(value < range)
  855.             break;
  856.         value -= range;
  857.     }
  858.  
  859.     if((code = push_font(context, font_no, 0)) < 0)
  860.         return code;
  861.  
  862.     context->str += width - 1;
  863.     context->len -= width - 1;
  864.     *context->str = value;
  865.     
  866.     return 0;
  867. }
  868.  
  869. /*
  870.  * Double Escape Mapping Decoder
  871.  */
  872.  
  873. private int
  874. FMapType7(struct context *context)
  875. {
  876.         byte esc_char;
  877.     int code, font_no;
  878.     gs_font *pfont = context->fontstack[context->fdepth];
  879.     
  880.     if(context->len <= 0)
  881.         return e_rangecheck;
  882.  
  883.     esc_char = pfont->data.type0_data.EscChar;
  884.  
  885.     if(context->str[0] == esc_char) {
  886.         if(context->str[1] == esc_char) {
  887.             /* Double Escape */
  888.             if(context->len < 4)
  889.                 return e_rangecheck;
  890.             font_no = context->str[2] + 256;
  891.             context->str += 3;
  892.             context->len -= 3;
  893.         }
  894.         else {
  895.             /* Single Escape */
  896.             if(context->len < 3)
  897.                 return e_rangecheck;
  898.             font_no = context->str[1];
  899.             context->str += 2;
  900.             context->len -= 2;
  901.         }
  902.  
  903.         if((code = push_font(context, font_no, 1)) < 0)
  904.             return code;
  905.  
  906.         /* 
  907.          * If the pushed font (i.e. currentfont) is a base font
  908.          * and the next character is the escape character again,
  909.          * then restore the parent composite font to currentfont.
  910.          */
  911.  
  912.         if((context->fontstack[context->fdepth]->FontType != 
  913.             ft_composite) && (context->str[0] == esc_char))
  914.             pop_font(context);
  915.     }
  916.     else {
  917.         if(context->font_no[context->fdepth] < 0)
  918.             context->font_no[context->fdepth] = 0;
  919.         font_no = context->font_no[context->fdepth];
  920.  
  921.         if((code = push_font(context, font_no, 1)) < 0)
  922.             return code;
  923.     }
  924.  
  925.     return 0;
  926. }
  927.  
  928. /*
  929.  * Shift Mapping Decoder
  930.  */
  931.  
  932. private int
  933. FMapType8(struct context *context)
  934. {
  935.         byte shift_in, shift_out;
  936.     int code, font_no;
  937.     gs_font *pfont = context->fontstack[context->fdepth];
  938.     
  939.     if(context->len <= 0)
  940.         return e_rangecheck;
  941.  
  942.     shift_in = pfont->data.type0_data.ShiftIn;
  943.     shift_out = pfont->data.type0_data.ShiftOut;
  944.  
  945.     if(context->str[0] == shift_in || context->str[0] == shift_out) {
  946.         if(context->len < 2)
  947.             return e_rangecheck;
  948.         if(context->str[0] == shift_in)
  949.             font_no = 0;
  950.         else
  951.             font_no = 1;
  952.         context->str ++;
  953.         context->len --;
  954.  
  955.         if((code = push_font(context, font_no, 1)) < 0)
  956.             return code;
  957.  
  958.         /* 
  959.          * If the pushed font (i.e. currentfont) is a base font
  960.          * and the next character is the shift character again,
  961.          * then restore the parent composite font to currentfont.
  962.          */
  963.  
  964.         if((context->fontstack[context->fdepth]->FontType != 
  965.             ft_composite) && (context->str[0] == shift_in || 
  966.                       context->str[0] == shift_out))
  967.             pop_font(context);
  968.     }
  969.     else {
  970.         if(context->font_no[context->fdepth] < 0)
  971.             context->font_no[context->fdepth] = 0;
  972.         font_no = context->font_no[context->fdepth];
  973.  
  974.         if((code = push_font(context, font_no, 1)) < 0)
  975.             return code;
  976.     }
  977.  
  978.     return 0;
  979. }
  980.  
  981. /*
  982.  * Push a font in the font stack
  983.  */
  984.  
  985. private int
  986. push_font(struct context *context, int font_no, int modal)
  987. {
  988.     ref *parent = &context->dictstack[context->fdepth];
  989.     gs_font *pfont = context->fontstack[context->fdepth];
  990.     gs_type0_data *pdata = &pfont->data.type0_data;
  991.     int code, font_index;
  992.     ref *child, *pid, *pfdepvector;
  993.  
  994.     /* pdata->FDepVector is not used because it might be out of date. */
  995.     if((code = dict_find(parent, &name_FDepVector, &pfdepvector)) < 0) 
  996.         return code;
  997. #ifdef DEBUG
  998.     fprintf(stderr, "push_font: pfdepvector->value.refs = %08X\n",
  999.         pfdepvector->value.refs);
  1000. #endif
  1001.     /* Retrieve the index to a child font */
  1002.     if(font_no >= pdata->encoding_size)
  1003.         return e_rangecheck;
  1004.     if((font_index = pdata->Encoding[font_no]) >= pdata->fdep_size)
  1005.         return e_invalidfont;
  1006.  
  1007.     /* Set mapping information */
  1008.     context->font_no[context->fdepth] = font_no;
  1009.     context->modal[context->fdepth] = modal;
  1010.  
  1011.     /* Push the font in the stack */
  1012.     context->fdepth ++;
  1013.     child = &pfdepvector->value.refs[font_index];
  1014.     context->dictstack[context->fdepth] = *child;
  1015.  
  1016.     /* pdata->FDepVector is not used because it could be wrong. */
  1017.     if((code = dict_find(child, &name_FID, &pid)) < 0) 
  1018.         return code;
  1019.     context->fontstack[context->fdepth] = pid->value.pfont;
  1020.  
  1021.     /* Initialize mapping information */
  1022.     context->font_no[context->fdepth] = -1;    /* specify undefined */
  1023.     context->modal[context->fdepth] = -1;    /* specify undefined */
  1024.  
  1025.     return 0;
  1026. }
  1027.  
  1028. /*
  1029.  * Pop fonts from the font stack until a modal font comes up
  1030.  */
  1031.  
  1032. private int 
  1033. pop_font(struct context *context)
  1034. {
  1035.     while(context->fdepth > 0) {
  1036.         context->fdepth --;
  1037.         if(context->modal[context->fdepth])
  1038.             break;
  1039.     }
  1040.     return 0;
  1041. }
  1042.  
  1043. /*
  1044.  * Retrieve the widthshow character from the context
  1045.  */
  1046.  
  1047. private int
  1048. getwschar(struct context *context)
  1049. {
  1050.     char_code wschar = context->wschar, offset;
  1051.     int fdepth = context->fdepth;
  1052.     
  1053.     if(fdepth == 0)
  1054.         return wschar;
  1055.     switch(context->fontstack[fdepth - 1]->data.type0_data.FMapType) {
  1056.     case 4:
  1057.     case 5:
  1058.         offset = context->font_no[fdepth - 1]*128;
  1059.         break;
  1060.     case 2:
  1061.     case 3:
  1062.     case 6:
  1063.     case 7:
  1064.     case 8:
  1065.         offset = context->font_no[fdepth - 1]*256;
  1066.         break;
  1067.     default:
  1068.         return e_invalidfont;
  1069.     }
  1070.  
  1071.     if(wschar < offset || wschar > offset + 255)
  1072.         return e_rangecheck;
  1073. #ifdef DEBUG
  1074.     fprintf(stderr, "font_no: %02X, wschar: %02X\n", 
  1075.         context->font_no[fdepth - 1], wschar);
  1076. #endif
  1077.     return wschar - offset;
  1078. }
  1079.  
  1080. /*
  1081.  * Set Basefont
  1082.  */
  1083.  
  1084. private int
  1085. comp_setfont(struct context *context)
  1086. {
  1087.     int code;
  1088.     gs_matrix mat;
  1089.     gs_font *pfont, *newfont, *ffont;
  1090.     ref *pdict;
  1091.  
  1092.     /* If the font to be set is the current font, nothing be done. */
  1093.     if(context->fdepth == 0)
  1094.         return 0;
  1095.  
  1096.     gs_make_identity(&mat);
  1097.     if(context->fdepth != 0) {
  1098.         gs_font *pfont = context->fontstack[context->fdepth - 1];
  1099.         gs_matrix_multiply(&mat, &pfont->FontMatrix, &mat);
  1100.     }
  1101.  
  1102.     pdict = &context->dictstack[context->fdepth];
  1103.     pfont = context->fontstack[context->fdepth];
  1104.  
  1105.     /* Make new font */
  1106.     if((code = gs_makefont(ifont_dir, pfont, &mat, &newfont, &ffont)) <0)
  1107.         return code;
  1108.  
  1109.     /* In cshow it's necessary to set the correct font dictionary in 
  1110.        istate.font, otherwise we need not care about FontMatrix of 
  1111.        the font dictionary to be set in istate.font */
  1112.     if(context->in_cshow) {
  1113.         ref newdict, newmat, *mbody;
  1114.  
  1115.         if((code = dict_create(dict_maxlength(pdict), &newdict)) < 0 ||
  1116.            (code = dict_copy(pdict, &newdict)) < 0)
  1117.             return code;
  1118.  
  1119.         /* Put FontMatrix into the new dictionary */
  1120.         if((mbody = alloc_refs(6, "comp_setfont")) == 0)
  1121.             return e_VMerror;
  1122.         make_tasv_new(&newmat, t_array, a_all, 6, refs, mbody);
  1123.         *(gs_matrix *)mbody = newfont->FontMatrix;
  1124.         if((code = dict_put(&newdict, 
  1125.                     &name_FontMatrix, &newmat)) < 0 ||
  1126.            (code = add_FID(&newdict, newfont)) < 0)
  1127.             return code;
  1128.         /* Set the dictionary readonly */
  1129.         r_clear_attrs(dict_access_ref(&newdict), a_write);
  1130.  
  1131.         pdict = &newdict;
  1132.     }
  1133.  
  1134.     /* Set new font */
  1135.     if((code= gs_setfont(igs, newfont)) < 0)
  1136.         return code;
  1137.     istate.font = *pdict;
  1138.     return 0;
  1139. }
  1140.